package com.nlp.server.utils;

import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import com.nlp.common.core.exception.ServiceException;
import com.nlp.server.properties.BaiDuProperties;
import okhttp3.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.IOException;

/**
 * 百度工具类
 * @author shiliuyinzhen
 */
@Component
public class BaiDuUtils {

    @Autowired
    private BaiDuProperties baiDuProperties;

    private final OkHttpClient HTTP_CLIENT = new OkHttpClient().newBuilder().build();

    /** 获取到的token */
    private String accessToken;


    /**
     *
     * @param format 语音文件的格式，pcm/wav/amr/m4a。不区分大小写。推荐pcm文件
     * @param rate 采样率，16000、8000，固定值
     * @param devPid 不填写lan参数生效，都不填写，默认1537（普通话 输入法模型）
     * @param len 本地语音文件的的字节数，单位字节
     * @param speech 本地语音文件的二进制语音数据 ，需要进行 base64 编码。与len参数连一起使用。
     * @return
     */
    public String getTextByShortVoice(String format, Integer rate,Integer devPid, Integer len,String speech){
        MediaType mediaType = MediaType.parse("application/json");
        String params = new JSONObject()
                .put("format",format)
                .put("rate", rate)
                .put("dev_pid", devPid)
                .put("channel", 1)
                .put("token",getAccessToken())
                .put("cuid", "baidu_workshop")
                .put("len", len)
                .put("speech", speech)
                .toString();

        RequestBody body = RequestBody.create(mediaType, params);
        Request request = new Request.Builder()
                .url("http://vop.baidu.com/server_api")
                .method("POST", body)
                .addHeader("Content-Type", "application/json")
                .addHeader("Accept", "application/json")
                .build();
        try (Response response = HTTP_CLIENT.newCall(request).execute()) {
            String responseBody = response.body().string();
            JSONObject jsonObject = new JSONObject(responseBody);
            if(!jsonObject.get("err_msg").equals("success.")){
                throw new ServiceException("转换失败：" + jsonObject);
            }
            JSONArray resultArray = jsonObject.getJSONArray("result");
            return resultArray.get(0).toString();
        } catch (IOException e) {
            throw new ServiceException("转换失败：" + e.getMessage());
        }
    }




    /**
     * 语音识别转化为文字(音频文件转写API)
     * @param speechUrl 音频url: 可使用百度云对象存储进行音频存储，生成云端可外网访问的url链接，
     *                  音频大小不超过500MB，url长度不超过2048字节
     * @param format 音频格式: ["mp3", "wav", "pcm","m4a","amr"]单声道，编码 16bits 位深
     * @param pid 语言类型: 80001（中文语音近场识别模型极速版）, 80006（中文音视频字幕模型，1737（英文模型）
     * @param rate 采样率: [16000] 固定值
     * @return 语音识别后的文字
     */
    public String getTextByVoice(String speechUrl, String format, Integer pid, Integer rate) {
        MediaType mediaType = MediaType.parse("application/json");
        String params = new JSONObject()
                .put("speech_url", speechUrl)
                .put("format", format)
                .put("pid", pid)
                .put("rate", rate)
                .toString();

        RequestBody body = RequestBody.create(mediaType, params);
        Request request = new Request.Builder()
                .url("https://aip.baidubce.com/rpc/2.0/aasr/v1/create?access_token=" + getAccessToken())
                .method("POST", body)
                .addHeader("Content-Type", "application/json")
                .addHeader("Accept", "application/json")
                .build();

        try (Response response = HTTP_CLIENT.newCall(request).execute()) {
            String responseBody = response.body().string();
            JSONObject jsonObject = new JSONObject(responseBody);
            // 检查是否有 task_id
            if (!jsonObject.containsKey("task_id")) {
                throw new ServiceException("创建音频转写任务失败：" + jsonObject.toString());
            }
            String taskId = jsonObject.getStr("task_id");
            return getTextByTaskId(taskId);
        } catch (IOException e) {
            throw new ServiceException("获取语音识别结果失败：" + e.getMessage());
        }
    }

    /**
     * 从用户的AK，SK生成鉴权签名（Access Token）
     *
     * @return 鉴权签名（Access Token）
     */
    public String getAccessToken() {
        if (accessToken != null) {
            return accessToken;
        }

        MediaType mediaType = MediaType.parse("application/x-www-form-urlencoded");
        String params = new StringBuilder()
                .append("grant_type=client_credentials&client_id=")
                .append(baiDuProperties.getApiKey())
                .append("&client_secret=")
                .append(baiDuProperties.getSecretKey())
                .toString();

        RequestBody body = RequestBody.create(mediaType, params);
        Request request = new Request.Builder()
                .url("https://aip.baidubce.com/oauth/2.0/token")
                .method("POST", body)
                .addHeader("Content-Type", "application/x-www-form-urlencoded")
                .build();

        try (Response response = HTTP_CLIENT.newCall(request).execute()) {
            String responseBody = response.body().string();
            String token = new JSONObject(responseBody).getStr("access_token");
            accessToken = token;
            return token;
        } catch (IOException e) {
            throw new ServiceException("获取access_token失败：" + e.getMessage());
        }
    }

    /**
     * 根据任务id获取转换结果
     * @param taskId 任务id
     * @return 识别结果
     */
    public String getTextByTaskId(String taskId) {
        MediaType mediaType = MediaType.parse("application/json");
        String params = new JSONObject()
                .put("task_ids", new JSONArray().put(taskId))
                .toString();

        RequestBody body = RequestBody.create(mediaType, params);
        Request request = new Request.Builder()
                .url("https://aip.baidubce.com/rpc/2.0/aasr/v1/query?access_token=" + getAccessToken())
                .method("POST", body)
                .addHeader("Content-Type", "application/json")
                .addHeader("Accept", "application/json")
                .build();

        try {
            while (true) {
                try (Response response = HTTP_CLIENT.newCall(request).execute()) {
                    String responseBody = response.body().string();
//                    System.out.println("根据任务id获取转换结果response:" + responseBody);

                    JSONObject jsonObject = new JSONObject(responseBody);
                    JSONArray tasksInfoArray = jsonObject.getJSONArray("tasks_info");

                    if (tasksInfoArray.size() == 0) {
                        throw new ServiceException("tasks_info 数组为空");
                    }

                    JSONObject taskInfo = tasksInfoArray.getJSONObject(0);
                    String taskStatus = taskInfo.getStr("task_status");

                    if (taskStatus == null) {
                        throw new ServiceException("任务状态为空");
                    }

                    if (taskStatus.equals("Failure")) {
                        throw new ServiceException("转写失败：" + taskInfo.getStr("task_result"));
                    }

                    if (taskStatus.equals("Success")) {
                        JSONArray taskResultArray = jsonObject.getJSONArray("task_result");
                        if (taskResultArray.size() > 0) {
                            return taskResultArray.getJSONObject(0).getStr("result");
                        }
                        throw new ServiceException("任务结果为空");
                    }

                    // 睡眠500ms，等待转换结果完成
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    throw new RuntimeException("线程被中断", e);
                }
            }
        } catch (IOException e) {
            throw new ServiceException("根据任务id获取转换结果失败：" + e.getMessage());
        }
    }
}
